package us.versus.them.b3ge.events;

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;

/**
 *
 * Key provides a simple way to handle keyboard
 * handling using a simple callback registry mechanism.
 *
 * Callbacks are registered via the setCallback method.
 * The key and a function that takes no args and returns 
 * void are the inputs
 *
 * It listens to an EventDispatcher. When a key is pressed 
 * the callback is retrieved from the map and invoked.
 * 
 * Additionally there is a synchronous method "isDown" 
 * which returns true if the given key is held down at the 
 * time.
 *
 */ 
class Key {

	public var down : Hash< Bool >;
	public var callbock : Hash< Void -> Void >;

	/**
	 *
	 * create a new Key which, optionally, listens to a 
	 * supplied EventDispatcher
	 *
	 */
	public function new( ?eventDispatcher:EventDispatcher ) {
		down = new Hash< Bool >();
		callbock = new Hash< Void -> Void >();
		if ( null != eventDispatcher ) {
			this.listen( eventDispatcher );
		}
	}

	/**
	 *
	 * 
	 *
	 */
	public function listen( eventDispatcher:EventDispatcher ) {
		eventDispatcher.addEventListener( KeyboardEvent.KEY_DOWN, keyDown, false );
		eventDispatcher.addEventListener( KeyboardEvent.KEY_UP, keyUp, false );
	}

	/**
     *
     * check the status of a keyCode: is it held down 
	 * at the moment?
     *
     */
	public function isDown( keyCode:Int ) : Bool {
		return down.get( '' + keyCode );
	}

	/**
     *
     * register a callback function for a keyCode 
     *
	 */
	public function setCallBack( keyCode:Int, f:Void -> Void ) {
		callbock.set( '' + keyCode, f );
	}

	/**
     *
     * typically this is invoked from an EventDispatcher
     * it also checks the status of various modifier keys
     *
	 */
	public function keyUp( event : KeyboardEvent ) {
		up( event.keyCode );
		if ( event.altKey ) up( K_ALT );
		if ( event.ctrlKey ) up( K_CTRL );
		if ( event.shiftKey ) up( K_SHIFT );
	}

	/**
     *
     * typically this is invoked from an EventDispatcher
     * it also checks the status of various modifier keys
     *
	 */
	public function keyDown( event : KeyboardEvent ) {
		dwn( event.keyCode );
		if ( event.altKey ) dwn( K_ALT );
		if ( event.ctrlKey ) dwn( K_CTRL );
		if ( event.shiftKey ) dwn( K_SHIFT );
	}

	/**
     *
	 * when a key is pressed down
     *
     */
	public function dwn( keyCode:UInt ) {
		//trace( 'down ' + keyCode );
		down.set( '' + keyCode, true );
		var f = callbock.get( '' + keyCode );
		if ( null != f ) {
			f();
		}
	}

	/**
     *
	 * when a key is released
     *
     */
	public function up( keyCode:UInt ) {
		//trace( 'up ' + keyCode );
		down.remove( '' + keyCode );
	}

	/**
	 *
	 * Follows a list of common key codes 
	 *
	 */
	public static var K_BACKSPACE         = 8;
	public static var K_TAB               = 9;
	public static var K_ENTER             = 13;
	public static var K_SHIFT             = 16;
	public static var K_CTRL              = 17;
	public static var K_ALT               = 18;
	public static var K_PAUSE_BREAK       = 19;
	public static var K_CAPS_LOCK         = 20;
	public static var K_ESCAPE            = 27;
	public static var K_PAGE_UP           = 33;
	public static var K_SPACE             = 32;
	public static var K_PAGE_DOWN         = 34;
	public static var K_END               = 35;
	public static var K_HOME              = 36;
	public static var K_ARROW_LEFT        = 37;
	public static var K_ARROW_UP          = 38;
	public static var K_ARROW_RIGHT       = 39;
	public static var K_ARROW_DOWN        = 40;
	public static var K_PRINT_SCREEN      = 44;
	public static var K_INSERT            = 45;
	public static var K_DELETE            = 46;
	public static var K_0                 = 48;
	public static var K_1                 = 49;
	public static var K_2                 = 50;
	public static var K_3                 = 51;
	public static var K_4                 = 52;
	public static var K_5                 = 53;
	public static var K_6                 = 54;
	public static var K_7                 = 55;
	public static var K_8                 = 56;
	public static var K_9                 = 57;
	public static var K_A                 = 65;
	public static var K_B                 = 66;
	public static var K_C                 = 67;
	public static var K_D                 = 68;
	public static var K_E                 = 69;
	public static var K_F                 = 70;
	public static var K_G                 = 71;
	public static var K_H                 = 72;
	public static var K_I                 = 73;
	public static var K_J                 = 74;
	public static var K_K                 = 75;
	public static var K_L                 = 76;
	public static var K_M                 = 77;
	public static var K_N                 = 78;
	public static var K_O                 = 79;
	public static var K_P                 = 80;
	public static var K_Q                 = 81;
	public static var K_R                 = 82;
	public static var K_S                 = 83;
	public static var K_T                 = 84;
	public static var K_U                 = 85;
	public static var K_V                 = 86;
	public static var K_W                 = 87;
	public static var K_X                 = 88;
	public static var K_Y                 = 89;
	public static var K_Z                 = 90;
	public static var K_LEFT_WINDOW_KEY   = 91;
	public static var K_RIGHT_WINDOW_KEY  = 92;
	public static var K_SELECT_KEY        = 93;
	public static var K_NUMPAD_0          = 96;
	public static var K_NUMPAD_1          = 97;
	public static var K_NUMPAD_2          = 98;
	public static var K_NUMPAD_3          = 99;
	public static var K_NUMPAD_4          = 100;
	public static var K_NUMPAD_5          = 101;
	public static var K_NUMPAD_6          = 102;
	public static var K_NUMPAD_7          = 103;
	public static var K_NUMPAD_8          = 104;
	public static var K_NUMPAD_9          = 105;
	public static var K_MULTIPLY          = 106;
	public static var K_ADD               = 107;
	public static var K_SUBTRACT          = 109;
	public static var K_DECIMAL_POINT     = 110;
	public static var K_DIVIDE            = 111;
	public static var K_F1                = 112;
	public static var K_F2                = 113;
	public static var K_F3                = 114;
	public static var K_F4                = 115;
	public static var K_F5                = 116;
	public static var K_F6                = 117;
	public static var K_F7                = 118;
	public static var K_F8                = 119;
	public static var K_F9                = 120;
	public static var K_F10               = 121;
	public static var K_F11               = 122;
	public static var K_F12               = 123;
	public static var K_NUM_LOCK          = 144;
	public static var K_SCROLL_LOCK       = 145;
	public static var K_MY_COMPUTER       = 182;
	public static var K_MY_CALCULATOR     = 183;
	public static var K_SEMICOLON         = 186;
	public static var K_EQUAL_SIGN        = 187;
	public static var K_COMMA             = 188;
	public static var K_DASH              = 189;
	public static var K_PERIOD            = 190;
	public static var K_FORWARD_SLASH     = 191;
	public static var K_OPEN_BRACKET      = 219;
	public static var K_BACK_SLASH        = 220;
	public static var K_CLOSE_BRAKET      = 221;
	public static var K_SINGLE_QUOTE      = 222;

	// http://www.aspdotnetfaq.com/Faq/What-is-the-list-of-KeyCodes-for-JavaScript-KeyDown-KeyPress-and-KeyUp-events.aspx

}
